unit DIrr.Buffer;

{$I DIrr.inc}

interface

uses
  DIrr.Base, DIrr.Types, DIrr.AabBox3D, DIrr.Vector3D, DIrr.Vector2D,
  DIrr.Structs;

type
  TVertexBuffer = class(TNamedObject)
  public
    function GetData: Pointer; virtual; stdcall; abstract;
    function GetType: E_VERTEX_TYPE; virtual; stdcall; abstract;
    procedure SetType(VertexType: E_VERTEX_TYPE); virtual; stdcall; abstract;
    function Stride: U32; virtual; stdcall; abstract;
    function Size: U32; virtual; stdcall; abstract;
    procedure PushBack(const Element: S3DVertex); virtual; stdcall; abstract;
    function GetVertex(const Index: U32): P3DVertex; virtual; stdcall; abstract;
    function GetLast: P3DVertex; virtual; stdcall; abstract;
    procedure SetUsed(UsedNow: U32); virtual; stdcall; abstract;
    procedure Reallocate(NewSize: u32); virtual; stdcall; abstract;
    function AllocatedSize: U32; virtual; stdcall; abstract;
    function GetPointer: P3DVertex; virtual; stdcall; abstract;

		//! get the current hardware mapping hint
    function GetHardwareMappingHint: E_HARDWARE_MAPPING; virtual; stdcall; abstract;

		//! set the hardware mapping hint, for driver
    procedure SetHardwareMappingHint(NewMappingHint: E_HARDWARE_MAPPING); virtual; stdcall; abstract;

		//! flags the meshbuffer as changed, reloads hardware buffers
    procedure SetDirty; virtual; stdcall; abstract;

		//! Get the currently used ID for identification of changes.
		(** This shouldn't be used for anything outside the VideoDriver. *)
    function GetChangedID: u32; virtual; stdcall; abstract;
  end;

  TIndexBuffer = class(TNamedObject) //IIndexBuffer.h
  public
    function GetData: Pointer; virtual; stdcall; abstract;
    function GetType: E_INDEX_TYPE; virtual; stdcall; abstract;
    procedure SetType(IndexType: E_INDEX_TYPE); virtual; stdcall; abstract;
    function Stride: u32; virtual; stdcall; abstract;
    function Size: u32; virtual; stdcall; abstract;
    procedure PushBack(const Element: U32); virtual; stdcall; abstract;
    function GetIndex(Index: U32): U32; virtual; stdcall; abstract;
    function GetLast: u32; virtual; stdcall; abstract;
    procedure SetValue(Index: U32; Value: U32); virtual; stdcall; abstract;
    procedure SetUsed(UsedNow: U32); virtual; stdcall; abstract;
    procedure Reallocate(NewSize: u32); virtual; stdcall; abstract;
    function AllocatedSize: U32; virtual; stdcall; abstract;
    function Pointer: Pointer; virtual; stdcall; abstract;

		//! get the current hardware mapping hint
    function GetHardwareMappingHint: E_HARDWARE_MAPPING; virtual; stdcall; abstract;

		//! set the hardware mapping hint, for driver
    procedure SetHardwareMappingHint(NewMappingHint: E_HARDWARE_MAPPING); virtual; stdcall; abstract;

		//! flags the meshbuffer as changed, reloads hardware buffers
    procedure SetDirty; virtual; stdcall; abstract;

		//! Get the currently used ID for identification of changes.
		(** This shouldn't be used for anything outside the VideoDriver. *)
    function GetChangedID: u32; virtual; stdcall; abstract;
  end;

  TMeshBuffer = class abstract(TNamedObject)
  public
    function GetMaterial: Pointer; virtual; stdcall; abstract;
  {$HINTS OFF}
  strict private function __GetMaterial: Pointer; virtual; stdcall; abstract;  //C++ return const
  {$HINTS ON}
  public
    function GetVertexType: E_VERTEX_TYPE; virtual; stdcall; abstract;
  {$HINTS OFF}
  strict private function __GetVertices: Pointer; virtual; stdcall; abstract;  //C++ return const
  {$HINTS ON}
  public
    function GetVertices: Pointer; virtual; stdcall; abstract;
    function GetVertexCount: U32; virtual; stdcall; abstract;
    function GetIndexType: E_INDEX_TYPE; virtual; stdcall; abstract;
  {$HINTS OFF}
  strict private function __GetIndices: PU16; virtual; stdcall; abstract; //C++ return const
  {$HINTS ON}
  public
    function GetIndices: PU16; virtual; stdcall; abstract;
    function GetIndexCount: U32; virtual; stdcall; abstract;
    function GetBoundingBox: PAabBox3DF; virtual; stdcall; abstract;
    procedure SetBoundingBox(const Box: TAabBox3DF); virtual; stdcall; abstract;
    procedure RecalculateBoundingBox; virtual; stdcall; abstract;
  {$HINTS OFF}
  strict private function __GetPosition(i: U32): PVector3DF; virtual; stdcall; abstract; //C++ return const
  {$HINTS ON}
  public
    function GetPosition(i: U32): PVector3DF; virtual; stdcall; abstract;
  {$HINTS OFF}
  strict private function __GetNormal(i: U32): PVector3DF; virtual; stdcall; abstract; //C++ return const
  {$HINTS ON}
  public
    function GetNormal(i: U32): PVector3DF; virtual; stdcall; abstract;
  {$HINTS OFF}
  strict private function __GetTCoords(i: U32): PVector2DF; virtual; stdcall; abstract; //C++ return const
  {$HINTS ON}
  public
    function GetTCoords(i: U32): PVector2DF; virtual; stdcall; abstract;
    procedure Append(Vertices: Pointer; NumVertices: U32; Indices: PU16; NumIndices: U32); overload; virtual; stdcall; abstract;
    procedure Append(Other: TMeshBuffer); overload; virtual; stdcall; abstract;
    function GetHardwareMappingHint_Vertex: E_HARDWARE_MAPPING; virtual; stdcall; abstract;
    function GetHardwareMappingHint_Index: E_HARDWARE_MAPPING; virtual; stdcall; abstract;
    procedure SetHardwareMappingHint(NewMappingHint: E_HARDWARE_MAPPING;
      buffer: E_BUFFER_TYPE = EBT_VERTEX_AND_INDEX); virtual; stdcall; abstract;
    procedure SetDirty(buffer: E_BUFFER_TYPE = EBT_VERTEX_AND_INDEX); virtual; stdcall; abstract;
    function GetChangedID_Vertex: U32; virtual; stdcall; abstract;
    function GetChangedID_Index: U32; virtual; stdcall; abstract;
  end;

  TDynamicMeshBuffer = class(TMeshBuffer)
  public
    function GetVertexBuffer: TVertexBuffer; virtual; stdcall; abstract;
    function GetIndexBuffer: TIndexBuffer; virtual; stdcall; abstract;

    procedure SetVertexBuffer(VertexBuffer: TVertexBuffer); virtual; stdcall; abstract;
    procedure SetIndexBuffer(IndexBuffer: TIndexBuffer); virtual; stdcall; abstract;

		//! Get the material of this meshbuffer
		(** \return Material of this buffer. *)
    //function GetMaterial: PMaterial; virtual; stdcall; abstract;

		//! Get the material of this meshbuffer
		(** \return Material of this buffer. *)
    function _const_GetMaterial: PMaterial; virtual; stdcall; abstract;

		//! Get the axis aligned bounding box of this meshbuffer.
		(** \return Axis aligned bounding box of this buffer. *)
    //function GetBoundingBox: PAabBox3DF; virtual; stdcall; abstract;

		//! Set axis aligned bounding box
		(** \param box User defined axis aligned bounding box to use
		for this buffer. *)
    //procedure SetBoundingBox(const Box: TAabbox3DF); virtual; stdcall; abstract;

		//! Recalculates the bounding box. Should be called if the mesh changed.
    //procedure RecalculateBoundingBox; virtual; stdcall; abstract;

		//! Append the vertices and indices to the current buffer
		(** Only works for compatible vertex types.
		\param vertices Pointer to a vertex array.
		\param numVertices Number of vertices in the array.
		\param indices Pointer to index array.
		\param numIndices Number of indices in array. *)
    procedure Append(Vertices: Pointer; NumVertices: U32; Indices: PU16; NumIndices: U32); override;

		//! Append the meshbuffer to the current buffer
		(** Only works for compatible vertex types
		\param other Buffer to append to this one. *)
    procedure Append(Other: TMeshBuffer); override;

		// ------------------- To be removed? -------------------  //

		//! get the current hardware mapping hint
    function GetHardwareMappingHint_Vertex: E_HARDWARE_MAPPING; override;

		//! get the current hardware mapping hint
    function GetHardwareMappingHint_Index: E_HARDWARE_MAPPING; override;

		//! set the hardware mapping hint, for driver
    procedure SetHardwareMappingHint(NewMappingHint: E_HARDWARE_MAPPING;
      Buffer: E_BUFFER_TYPE = EBT_VERTEX_AND_INDEX); override;

		//! flags the mesh as changed, reloads hardware buffers
    procedure SetDirty(Buffer: E_BUFFER_TYPE = EBT_VERTEX_AND_INDEX); override;

    function GetChangedID_Vertex: u32; override;

    function GetChangedID_Index: u32; override;

		// ------------------- Old interface -------------------  //

		//! Get type of vertex data which is stored in this meshbuffer.
		(** \return Vertex type of this buffer. *)
    function GetVertexType: E_VERTEX_TYPE; override;

		//! Get access to vertex data. The data is an array of vertices.
		(** Which vertex type is used can be determined by getVertexType().
		\return Pointer to array of vertices. *)
    function GetVertices: Pointer; override;

  protected
		//! Get access to vertex data. The data is an array of vertices.
		(** Which vertex type is used can be determined by getVertexType().
		\return Pointer to array of vertices. *)
    function _const_GetVertices: Pointer; virtual; stdcall;

  public
		//! Get amount of vertices in meshbuffer.
		(** \return Number of vertices in this buffer. *)
    function GetVertexCount: u32; override;

		//! Get type of index data which is stored in this meshbuffer.
		(** \return Index type of this buffer. *)
    function GetIndexType: E_INDEX_TYPE; override;

		//! Get access to Indices.
		(** \return Pointer to indices array. *)
    function GetIndices: PU16; override;

  protected
		//! Get access to Indices.
		(** \return Pointer to indices array. *)
    function _const_GetIndices: PU16; virtual; stdcall;

  public
		//! Get amount of indices in this meshbuffer.
		(** \return Number of indices in this buffer. *)
    function GetIndexCount: u32; override;

		//! returns position of vertex i
    function GetPosition(i: U32): PVector3DF; override;

  protected
		//! returns position of vertex i
    function _const_GetPosition(i: U32): PVector3DF; virtual; stdcall;

  public
		//! returns texture coords of vertex i
    function GetTCoords(i: U32): PVector2DF; override;

  protected
		//! returns texture coords of vertex i
    function _const_GetTCoords(i: U32): PVector3DF; virtual; stdcall;

  public
		//! returns normal of vertex i
    function GetNormal(i: U32): PVector3DF; override;

  protected
		//! returns normal of vertex i
    function _const_GetNormal(i: U32): PVector3DF; virtual; stdcall;
  end;


implementation

{ TDynamicMeshBuffer }

procedure TDynamicMeshBuffer.Append(Other: TMeshBuffer);
begin
end;

procedure TDynamicMeshBuffer.Append(Vertices: Pointer; NumVertices: U32;
  Indices: PU16; NumIndices: U32);
begin
end;

function TDynamicMeshBuffer.GetChangedID_Index: u32;
begin
  Result := GetIndexBuffer.GetChangedID;
end;

function TDynamicMeshBuffer.GetChangedID_Vertex: u32;
begin
  Result := GetVertexBuffer.GetChangedID;
end;

function TDynamicMeshBuffer.GetHardwareMappingHint_Index: E_HARDWARE_MAPPING;
begin
  Result := GetIndexBuffer.GetHardwareMappingHint;
end;

function TDynamicMeshBuffer.GetHardwareMappingHint_Vertex: E_HARDWARE_MAPPING;
begin
  Result := GetVertexBuffer.GetHardwareMappingHint;
end;

function TDynamicMeshBuffer.GetIndexCount: u32;
begin
  Result := GetIndexBuffer.Size;
end;

function TDynamicMeshBuffer.GetIndexType: E_INDEX_TYPE;
begin
  Result := GetIndexBuffer.GetType;
end;

function TDynamicMeshBuffer.GetIndices: PU16;
begin
  Result := PU16(GetIndexBuffer.GetData);
end;

function TDynamicMeshBuffer.GetNormal(i: U32): PVector3DF;
begin
  Result := @(GetVertexBuffer.GetVertex(i)^.Normal);
end;

function TDynamicMeshBuffer.GetPosition(i: U32): PVector3DF;
begin
  Result := @(GetVertexBuffer.GetVertex(i)^.Pos);
end;

function TDynamicMeshBuffer.GetTCoords(i: U32): PVector2DF;
begin
  Result := @(GetVertexBuffer.GetVertex(i)^.TCoords);
end;

function TDynamicMeshBuffer.GetVertexCount: u32;
begin
  Result := GetVertexBuffer.Size;
end;

function TDynamicMeshBuffer.GetVertexType: E_VERTEX_TYPE;
begin
  Result := GetVertexBuffer.GetType;
end;

function TDynamicMeshBuffer.GetVertices: Pointer;
begin
  Result := GetVertexBuffer.GetData;
end;

procedure TDynamicMeshBuffer.SetDirty(Buffer: E_BUFFER_TYPE);
begin
  if Buffer in [EBT_VERTEX_AND_INDEX, EBT_VERTEX] then
    GetVertexBuffer.SetDirty;
  if Buffer in [EBT_VERTEX_AND_INDEX, EBT_INDEX] then
    GetIndexBuffer.SetDirty;
end;

procedure TDynamicMeshBuffer.SetHardwareMappingHint(
  NewMappingHint: E_HARDWARE_MAPPING; Buffer: E_BUFFER_TYPE);
begin
  if Buffer in [EBT_VERTEX_AND_INDEX, EBT_VERTEX] then
    GetVertexBuffer.SetHardwareMappingHint(NewMappingHint);
  if Buffer in [EBT_VERTEX_AND_INDEX, EBT_INDEX] then
    GetIndexBuffer.SetHardwareMappingHint(NewMappingHint);
end;

function TDynamicMeshBuffer._const_GetIndices: PU16;
begin
  Result := PU16(GetIndexBuffer.GetData);
end;

function TDynamicMeshBuffer._const_GetNormal(i: U32): PVector3DF;
begin
  Result := @(GetVertexBuffer.GetVertex(i)^.Normal);
end;

function TDynamicMeshBuffer._const_GetPosition(i: U32): PVector3DF;
begin
  Result := @(GetVertexBuffer.GetVertex(i)^.Pos);
end;

function TDynamicMeshBuffer._const_GetTCoords(i: U32): PVector3DF;
begin
  Result := @(GetVertexBuffer.GetVertex(i)^.TCoords);
end;

function TDynamicMeshBuffer._const_GetVertices: Pointer;
begin
  Result := GetVertexBuffer.GetData;
end;

end.
